package com.woniu.service.impl;


import cn.hutool.core.bean.BeanUtil;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.commons.exception.YogaException;
import com.woniu.commons.model.RedisKey;
import com.woniu.commons.model.StateData;
import com.woniu.commons.util.DigestUtil;
import com.woniu.commons.util.RedisUtil;
import com.woniu.dao.YAdminMapper;
import com.woniu.dao.YVenueMapper;
import com.woniu.model.dto.AdminDto;
import com.woniu.model.entity.YAdmin;
import com.woniu.model.entity.YCoach;
import com.woniu.model.entity.YVenue;
import com.woniu.model.param.*;
import com.woniu.service.YAdminService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 胡歌
 * @since 2024年05月22日
 */
@Service
public class YAdminServiceImpl extends ServiceImpl<YAdminMapper, YAdmin> implements YAdminService {
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private YAdminMapper adminMapper;
    @Resource
    private YVenueMapper venueMapper;

    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private RedissonClient redissonClient;//通过这个完成释放锁上锁等一系列操作，导入依赖后直接使用

    @Override
    public void sendRegisterCode(String mobile) {
        //判断手机号码是否在一分钟内是否发送短信
        if (redisUtil.exist(RedisKey.registerCodeOnMinute(mobile))) {
            throw new YogaException(500,"1分钟不能再次发送");
        }
        //判断该手机号码在一小时内的短信发送次数
        if (redisUtil.exist(RedisKey.sendMessageNumber(mobile))) {
            Integer number = Integer.parseInt(redisUtil.get(RedisKey.sendMessageNumber(mobile)));
            if (number >= 20) {
                throw new YogaException(500,"超过发送短信次数,请稍后再试");
            }
        }
        //判断手机号是否注册过
        QueryWrapper<YAdmin> wrapper = new QueryWrapper<>();
        wrapper.eq("admin_phone", mobile);

        YAdmin admin = adminMapper.selectOne(wrapper);

        if (admin != null) {
            throw new YogaException(500,"该手机号已注册");
        }
        //将手机号码保存到消息队列中
        rabbitTemplate.convertAndSend("register_phone_queue",mobile);
    }

    @Override
    public void CodeAdminRegister(CodeAdminRegisterParam param) throws Exception {
        //创建一把手机号码锁(公平锁)
        RLock phoneLock = redissonClient.getFairLock(RedisKey.phoneLock(param.getAdminPhone()));
        //创建一把用户名锁（公平锁）
        RLock userNameLock = redissonClient.getFairLock(RedisKey.userNameLock(param.getAdminName()));
        //变成多资源锁；这里放进该方法的顺序就是加锁的顺序
        RLock lock = redissonClient.getMultiLock(phoneLock, userNameLock);

        if (lock.tryLock(10, TimeUnit.SECONDS)) {
            //设置10秒；代表成功
            try {//一定要用try块包括成功，finally成功与否都要释放锁

                //首先判断总错误次数
                if (redisUtil.exist(RedisKey.codeErrorNumber(param.getAdminPhone()))) {
                    if (Integer.parseInt(redisUtil.get(RedisKey.codeErrorNumber(param.getAdminPhone()))) >= 5) {
                        throw new Exception("超过最大次数限制，验证码失效");
                    }
                }

                //先判断验证码是否正确
                if (!param.getCode().equals(redisUtil.get(RedisKey.registerCodeKey(param.getAdminPhone())))) {
                    //验证码错误，就给他的错误总次数+1
                    if (redisUtil.exist(RedisKey.codeErrorNumber(param.getAdminPhone()))) {
                        redisUtil.incr(RedisKey.codeErrorNumber(param.getAdminPhone()));
                        if (Integer.parseInt(redisUtil.get(RedisKey.codeErrorNumber(param.getAdminPhone()))) >= 5) {
                            redisUtil.delete(RedisKey.registerCodeKey(param.getAdminPhone()));
                        }
                    } else {
                        redisUtil.set(RedisKey.codeErrorNumber(param.getAdminPhone()), "1", 5 * 60);
                    }
                    throw new Exception("验证码错误");
                }
                //判断手机号是否注册过
                QueryWrapper<YAdmin> wrapper = new QueryWrapper<YAdmin>();
                wrapper.eq("admin_phone", param.getAdminPhone());

                YAdmin admin = adminMapper.selectOne(wrapper);
                if (admin != null) {
                    throw new Exception("该手机号已注册");
                }
                //判断用户名是否已经被注册
                QueryWrapper<YAdmin> wrapper1 = new QueryWrapper<YAdmin>();
                wrapper1.eq("admin_name", param.getAdminName());
                YAdmin admin1 = adminMapper.selectOne(wrapper1);
                if (admin1 != null) {
                    throw new Exception("教练名已注册");
                }
                //执行注册
                admin = BeanUtil.toBean(param, YAdmin.class);
                //对密码加密
                String md5 = DigestUtil.md5(param.getAdminPassword(), param.getAdminName());
                admin.setAdminPassword(md5);
                admin.setAdminState(1);
                adminMapper.insert(admin);
                //删除验证码
                redisUtil.delete(RedisKey.registerCodeKey(param.getAdminPhone()));
            } finally {
                lock.unlock();//释放锁
            }

        } else {
            //代表失败
            throw new Exception("服务器繁忙");
        }
    }

    @Override
    public void LoginCodePhone(String mobile) throws Exception {
        if (redisUtil.exist(RedisKey.loginCodeOnMinuteKey(mobile))) {
            throw new YogaException(5001,"1分钟不能再次发送");
        }
        if (redisUtil.exist(RedisKey.sendMessageNumber(mobile))) {
            int num = Integer.parseInt(redisUtil.get(RedisKey.sendMessageNumber(mobile)));
            if (num >= 5) {
                throw new YogaException(500,"超过发送短信次数,请稍后再试");
            }
        }
        QueryWrapper<YAdmin> wrapper = new QueryWrapper<YAdmin>();
        wrapper.eq("admin_phone", mobile);
        YAdmin admin = adminMapper.selectOne(wrapper);
        if (admin == null) {
            throw new YogaException(5002,"手机号尚未注册");
        }
        //将手机号存入消息队列
        rabbitTemplate.convertAndSend("login_code_queue",mobile);
    }

    @Override
    public AdminDto codeLogin(AdminCodeLoginParam param) throws Exception {
        //如果存在错误次数的键 判断次数是否大于5
        if (redisUtil.exist(RedisKey.codeErrorNumber(param.getAdminPhone()))) {
            if ((Integer.parseInt(redisUtil.get(RedisKey.codeErrorNumber(param.getAdminPhone())))) >= 5) {
                throw new YogaException(5003,"验证码错误次数达到上限");
            }
        }
        //传过来的验证码如果不等于redis存入的验证码
        if (!param.getCode().equals(redisUtil.get(RedisKey.loginCodeKey(param.getAdminPhone())))) {
            //存在输入验证码错误次数限制
            if (redisUtil.exist(RedisKey.codeErrorNumber(param.getAdminPhone()))) {
                //输入验证码错误次数加1
                redisUtil.incr(RedisKey.codeErrorNumber(param.getAdminPhone()));
                //输入验证码错误次数5 删除redis中的验证码 无效了
                if ((Integer.parseInt(redisUtil.get(RedisKey.codeErrorNumber(param.getAdminPhone())))) >= 5) {
                    redisUtil.delete(RedisKey.loginCodeKey(param.getAdminPhone()));
                }

            } else {
                //如果不存在输入验证码错误次数限制 添加一个
                redisUtil.set(RedisKey.codeErrorNumber(param.getAdminPhone()), "1", 5 * 60);
            }
            throw new YogaException(5005,"验证码错误");
        }
        QueryWrapper<YAdmin> wrapper = new QueryWrapper<YAdmin>();
        wrapper.eq("admin_phone", param.getAdminPhone());
        YAdmin admin = adminMapper.selectOne(wrapper);
        if (admin == null) {
            throw new YogaException(5006,"教练不存在");
        }
        AdminDto dto = new AdminDto();
        dto.setAdminName(admin.getAdminName());
        dto.setId(admin.getAdminId());
        return dto;
    }

    @Override
    public AdminDto adminLogin(adminLoginParam param) throws Exception {
        QueryWrapper<YAdmin> wrapper = new QueryWrapper<YAdmin>();
        wrapper.eq("admin_name", param.getAdminName());
        YAdmin admin = adminMapper.selectOne(wrapper);
        if (admin == null) {
            throw new YogaException(5002,"尚未注册");
        }
        System.out.println(DigestUtil.md5(param.getAdminPassword(), param.getAdminName()));
        System.out.println(admin.getAdminPassword()+"===========");
        if (!admin.getAdminPassword().equals(DigestUtil.md5(param.getAdminPassword(), param.getAdminName()))) {
            throw new YogaException(5005,"密码错误");
        }
        if (admin.getAdminState()==0){
            throw new YogaException(5006,"状态异常请联系超管");
        }
        AdminDto dto = new AdminDto();
        dto.setId(admin.getAdminId());
        dto.setAdminName(admin.getAdminName());
        return dto;
    }

//    public AdminDto adminLogin(adminLoginParam param) throws Exception {
//        QueryWrapper<YAdmin> wrapper = new QueryWrapper<>();
//        wrapper.eq("admin_name", param.getAdminName());
//        YAdmin admin = adminMapper.selectOne(wrapper);
//        if (admin == null) {
//            throw new YogaException(5002, "尚未注册");
//        }
//        String inputPasswordHash = DigestUtil.md5(param.getAdminPassword(), param.getAdminName());
//        System.out.println(inputPasswordHash);
//        if (!admin.getAdminPassword().equals(inputPasswordHash)) {
//            throw new YogaException(5005, "密码错误");
//        }
//        if (admin.getAdminState() == 0) {
//            throw new YogaException(5006, "状态异常请联系超管");
//        }
//        AdminDto dto = new AdminDto();
//        dto.setId(admin.getAdminId());
//        dto.setAdminName(admin.getAdminName());
//        return dto;
//    }

    @Override
    public void disable(Integer adminId) {
        YAdmin admin = adminMapper.selectById(adminId);
        if(Objects.equals(admin.getAdminState(), StateData.ADMIN_STATE_DISABLED)){
            throw new YogaException(20001,"类别状态异常");
        }
        admin.setAdminState(0);
        adminMapper.updateById(admin);
    }

    @Override
    public void enable(Integer adminId) {
        YAdmin admin = adminMapper.selectById(adminId);
        if(Objects.equals(admin.getAdminState(), StateData.ADMIN_STATE_NORMAL)){
            throw new YogaException(20001,"类别状态异常");
        }
        admin.setAdminState(1);
        adminMapper.updateById(admin);
    }

    @Override
    public Page<YAdmin> loadPageAdmin(loadPageAllAdminParam param) throws YogaException {
        if (param.getPageNum() == null) {
            param.setPageNum(1);
        }
        if (param.getPageSize() == null) {
            param.setPageSize(5);
        }
        Page<YAdmin> page = new Page<>(param.getPageNum(), param.getPageSize());
        QueryWrapper<YAdmin> wrapper = new QueryWrapper<>();
        wrapper.like("admin_name",param.getAdminName());
        return  adminMapper.selectPage(page, wrapper);
    }

    @Override
    public void checkPhone(Long phone) {
        YAdmin admin = baseMapper.selectOne(new QueryWrapper<YAdmin>().eq("admin_phone", phone));
        if (admin!=null){
            throw new YogaException(3001,"当前号码已注册管理员");
        }
    }


//    @Override
//    public YVenue updateVenue(AdminUpdateVenueParam param) {
//        YVenue venue = venueMapper.selectById(param.getVenueId());
//        venue.setVenueId(param.getVenueId());
//        venue.setVenueState(param.getVenueState());
//        venue.setVenueDetail(param.getVenueDetail());
//        adminMapper.updateById(BeanUtil.toBean(venue,YAdmin.class));
//        return venue;
//    }

//    @Override
//    public YCoach updateCoach(AdminUpdateCoachStateParam param) {
//        YCoach coach = new YCoach();
//        coach.setCoachId(param.getCoachId());
//        coach.setCoachState(param.getCoachState());
//        adminMapper.updateById(BeanUtil.toBean(coach,YAdmin.class));
//        return coach;
//    }
}
